import wx
import sys
import os
import socket
import random

from shutil import move
from threading import Thread
from webbrowser import open_new
from helpers import forceunicode, isPathRelative, fixInvalidName, fixWindowsName, existsAndIsReadable
from regchecker import RegChecker
from configreader import ConfigReader
from lang import Lang

from LMG.Actions.makeactions import makeActionList

from BitTornado.ConfigDir import ConfigDir
from BitTornado.__init__ import product_name, version_short, home_page
from BitTornado.bencode import bdecode
from BitTornado.download_bt1 import defaults as BTDefaults
from BitTornado.parseargs import parseargs
from BitTornado.BTcrypto import CRYPTO_OK
from BitTornado.zurllib import urlopen

from constants import *

# For computer shutdown
if (sys.platform == 'win32'):
    from win32con import VER_PLATFORM_WIN32_NT, VER_PLATFORM_WIN32_WINDOWS
    if sys.getwindowsversion()[3] == VER_PLATFORM_WIN32_NT:
        from win32api import GetCurrentProcess, ExitWindowsEx
        from win32security import OpenProcessToken, LookupPrivilegeValue, AdjustTokenPrivileges
        from win32con import TOKEN_ALL_ACCESS, SE_SHUTDOWN_NAME, SE_PRIVILEGE_ENABLED

################################################################
#
# Class: Utility
#
# Generic "glue" class that contains commonly used helper
# functions and helps to keep track of objects
#
################################################################    
class Utility:
    """
    # Generic "glue" class that contains commonly used helper
    # functions and helps to keep track of objects
    """
    def __init__(self, path):
        self.path = path
        self.browsers = []
        self.browser = ""
        self.quitting = False
        self.configdir = None
        self.dir_root = self.setupConfigPath()
        self.MakeDir("torrent")
        self.MakeDir("database")
        self.MakeDir("tracker")
        self.MakeDir("ipfilter")
        self.MoveOldFiles()
        
        # Set Lang
        self.lang = Lang(self)

        # Reg Checker
        self.regchecker = RegChecker(self)
        
        # Keep track of torrents
        self.setupTorrentList()
        self.torrents = { "all": [], 
                          "active": {}, 
                          "inactive": {}, 
                          "paused": {}, 
                          "seeding": {}, 
                          "downloading": {} }
        self.activeGroup = "all"
                          
        # Keep track of all the "ManagedList" objects in use
        self.lists = {}
        self.imagelist = None
        self.images = {}

        # Set Config
        self.config         = self.setupConfig()
        self.webconfig      = self.setupWebConfig()
        self.makerconfig    = self.setupTorrentMakerConfig()
        self.lastdir = { "save" : self.config.Read('defaultfolder'), 
                         "open" : "", 
                         "log": "" }

        self.configdir.deleteOldCacheData(self.config.Read('expire_cache_data', "int"))

	# Install Open New command
        if os.name == "posix" and sys.platform != "darwin":
            self.install_open_new()
            
    def MoveOldFiles(self):            
        oldpath = self.getPath()
        newpath = self.getConfigPath()
        files = ["torrent.list",
                 "lh.conf",
                 "maker.conf",
                 "search.conf",
                 "torrent"]
        for name in files:
            oldname = os.path.join(oldpath, name)
            if existsAndIsReadable(oldname):
                newname = os.path.join(newpath, name)
                try:
                    move(oldname, newname)
                except:
                    pass
                
    def getLastDir(self, operation = "save"):
        lastdir = self.lastdir[operation]
        
        if operation == "save":
            if not os.access(lastdir, os.F_OK):
                lastdir = self.config.Read('defaultfolder')
        
        if not os.access(lastdir, os.F_OK):
            lastdir = ""
            
        return lastdir
    
    def MakeDir(self, strDir):
        path = os.path.join(self.getConfigPath(), strDir)
        pathexists = os.access(path, os.F_OK)
        # If the database directory doesn't exist, create it now
        if not pathexists:
            os.mkdir(path)
        
    def getDatabaseDir(self):
        return os.path.join(self.getConfigPath(), "database")
    
    def setupConfigPath(self):
        """
        Sets the config path at %appdata%
        """
        self.configdir = ConfigDir(local = wx.GetApp().local)
        return forceunicode(self.configdir.dir_root)

    def setupConfig(self):
        """
        Main config
        """
        if (sys.platform[:3] == 'win'):
            # Default directory for windows 
            defaultdir = "C:\\Downloads"
        else:
            # Default directory for unix
            defaultdir = os.path.join(os.path.expanduser('~'), "Downloads")
        defaults = {
                    # General
                    'lang': str(wx.LANGUAGE_DEFAULT),
                    'confirmonclose': '1',
                    'checkforupdates': '1',
                    'ipfilter': '1',
                    'filelogger': '0',
                    'rsstimer': '1800',
                    'rsstimerstatus': '1',
                    'hotkey': '0',
                    'hotkeymod': '0',
                    'hotkeykeycode': '0',
                    'hotkeywxkeycode': '0',
                    'associate' : '1',
                    'mintray_balloontips': '0',
                    'homepage': home_page,
                    
                    # Bandwidth
                    'maxupload': '5', 
                    'maxuploadrate': '0', 
                    'maxdownloadrate': '0', 
                    'maxseeduploadrate': '0', 
                    'numsimdownload': '2', 
                    'uploadtime': '0', 
                    'uploadratio': '150',
                    'maxuploadvolume': '0', 
                    'maxdownloadvolume': '0', 
                    'uploadvolume': '0', 
                    'downloadvolume': '0', 
                    
                    # Disk
                    'movecompleted': '0', 
                    'setdefaultfolder': '0', 
                    'defaultfolder': defaultdir,
                    'scandir': '',
                    'scandirfreq': '300',
                    'scandirmovetor': '1',
                    'defrentorwithdest': '1',
                    'diskfullthreshold': '0', 
                    'buffer_write' : '4', 
                    'buffer_read' : '1', 
                    'auto_flush' : '0',
                    'addlabeltomovedir': '0',
                    
                    # Security
                    'kickban': '1', 
                    'notsameip': '1', 
                    'scrape': '1',
                    'scrapequeued': '1',
                    
                    # BitTornado
                    'dht': '1',
                    'tracker': '0',
                    'pex_allowed': '0',
                    'expire_cache_data': '10',
                    'minport': "49152", 
                    'maxport': "65535",
                    'useport': "-1",
                    'ipv6': '0', 
                    'ipv6_binds_v4': '1', 
                    'min_peers': '20', 
                    'max_initiate': '40', 
                    'alloc_type': 'normal', 
                    'alloc_rate': '2', 
                    'max_files_open': '50', 
                    'max_connections': '60',    # no need for more than that 
                    'lock_files': '1', 
                    'lock_while_reading': '0', 
                    'double_check': '1', 
                    'triple_check': '0', 
                    'crypto_mode': str(int(CRYPTO_OK)),
                    'display_interval': '0.8',
                    'peercache': '60',

                    # Queue
                    'consideractive': '2',
                    'preferuncompleted': '0',
                    'timeouttracker': '15', 
                    'timeoutdownload': '30', 
                    'timeoutupload': '1', 
                    'defaultpriority': '2',
                    'defaultstatus': '1',
                    'autostart_upload': '0',
                    'autostart_upload_threshold': '10',
                    'autostart_upload_delay': '300',
                    'autostart_download': '0',
                    'autostart_download_threshold': '0',
                    'autostart_download_delay': '300',
                    'autostart_scrape': '0',
                    'autostart_scrape_value': '1',

                    # Constant
                    'fastresume': '1', 
                    'removetorrent': '1', 
                    'savecolumnwidth': '1',

                    # Network
                    'useportrange': '0', 
                    'upnp_nat_access': '0', 
                    'natpmp': '0',
                    'trackeraddress': '',
                    
                    # View
                    'peers_list_sort_colid': '-1',
                    'peers_list_sort_flag': '0',
                    'listfont': '', 
                    'allowmenubitmaps': '1',
                    'progress_bars': '0',
                    'show_statusbar': '1',
                    'show_toolbar': '1',
                    'show_inspector': '1',
                    'tb_size': '1',
                    'tb_style': '2',
                    'mintray': str(int(wx.Platform == "__WXMSW__")),
                    'maximized': '0',
                    'window_x': '',
                    'window_y': '',
                    'window_width': '792',
                    'window_height':'550',
                    'splitter_pos': '500',
                    'rss_column0_rank': '0',
                    'rss_column1_rank': '1',
                    'rss_column2_rank': '2',
                    'rss_column0_width': '335',
                    'rss_column1_width': '225',
                    'rss_column2_width': '200',
                    'statusbar1_rank': '1',
                    'statusbar2_rank': '1',
                    'statusbar3_rank': '1',
                    'statusbar4_rank': '1',
                    'column0_rank': '0',
                    'column1_rank': '1',
                    'column2_rank': '-1',
                    'column3_rank': '2',
                    'column4_rank': '3',
                    'column5_rank': '4',
                    'column6_rank': '5',
                    'column7_rank': '6',
                    'column8_rank': '7',
                    'column9_rank': '-1',
                    'column10_rank': '-1',
                    'column11_rank': '-1',
                    'column12_rank': '-1',
                    'column13_rank': '-1',
                    'column14_rank': '-1',
                    'column15_rank': '-1',
                    'column16_rank': '-1',
                    'column17_rank': '-1',
                    'column0_width': '235',
                    'column1_width': '85',
                    'column3_width': '75',
                    'column4_width': '75',
                    'column6_width': '80',
                    'column7_width': '75',
                    'column8_width': '75',
                    'column13_width': '80',
                    'column14_width': '80',
                    'column15_width': '80',
                    'column16_width': '80',
                    'column17_width': '80',
                    'fileinfo0_rank': '0',
                    'fileinfo0_width': '300', 
                    'fileinfo1_rank': '1',
                    'fileinfo1_width': '100', 
                    'fileinfo2_rank': '2',
                    'fileinfo2_width': '60', 
                    'fileinfo3_rank': '3',
                    'fileinfo3_width': '200', 
                    'fileinfo4_rank': '-1',
                    'fileinfo4_width': '200', 
                    'fileinfo5_rank': '-1',
                    'fileinfo5_width': '200', 
                    'fileinfo6_rank': '-1',
                    'fileinfo6_width': '200',
                    'icons_toolbartop':[ACTION_VIEWTRANSFER,
                                        ACTION_VIEWSEARCH,
                                        ACTION_VIEWRSS,
                                        ACTION_VIEWLOG,
                                        -1,
                                        ACTION_RESUME,
                                        ACTION_PAUSE,
                                        ACTION_STOP,
                                        ACTION_QUEUE,
                                        ACTION_REMOVE,
                                        -1,                                    
                                        ACTION_TORRENTDETAILS,
                                        ],
                    
                    'rightclickmenu': [ACTION_RESUME,
                                       ACTION_PAUSE,
                                       ACTION_STOP,
                                       ACTION_QUEUE,
                                       -1,
                                       ACTION_HASHCHECK,
                                       ACTION_SUPERSEED,
                                       ACTION_SCRAPE,
                                       -1,
                                       ACTION_REMOVE,
                                       ACTION_REMOVEFILE,
                                       -1,
                                       ACTION_SET_PRIORITY,
                                       ACTION_OPENDEST,
                                       ACTION_CHANGEDEST],
                    'taskbarmenu': [ACTION_EXIT]
                    }

        configfilepath = os.path.join(self.getConfigPath(), "lh.conf")
        return ConfigReader(configfilepath, "LH", defaults)

    def setupWebConfig(self):
        defaults = {
            'username': 'yourusername', 
            'password': '',
            'authorization': 'digest',
            'host': '127.0.0.1',
            'port': 56667,
            'webautostart': '0',
            'allow_quit': '1',
            'allow_version': '1',
            'allow_query': '1',
            'allow_getfiles': '1',
            'allow_setfileprio': '1',
            'allow_getsettings': '0',
            'allow_setsettings': '0',
            'allow_getprops': '1',
            'allow_setprops': '1',
            'allow_setpriority': '1',
            'allow_addurl': '1',
            'allow_addfile': '1',
            'allow_remove': '1',
            'allow_removedata': '0',
            'allow_queue': '1', 
            'allow_pause': '1', 
            'allow_stop': '1', 
            'allow_start': '1', 
            'allow_move': '1',
            'allow_superseed': '1',
            'allow_recheck': '1',
        }

        webconfigfilepath = os.path.join(self.getConfigPath(), "webservice.conf")
        return ConfigReader(webconfigfilepath, "LH/Webservice", defaults)

    def setupTorrentMakerConfig(self):
        """
        Torrent maker config
        """
        defaults = {
            'piece_size': '0', 
            'comment': '', 
            'created_by': '',
            'announcedefault': '', 
            'announcehistory': '', 
            'announce-list': '', 
            'dhtnodes': '', 
            'httpseeds': '', 
            'makehash_md5': '0', 
            'makehash_crc32': '0', 
            'makehash_sha1': '0', 
            'startnow': '0', 
            'savetorrent': '2',
            'privatetorrent': '0'
        }

        torrentmakerconfigfilepath = os.path.join(self.getConfigPath(), "maker.conf")
        return ConfigReader(torrentmakerconfigfilepath, "LH/TorrentMaker", defaults)
            
    def getConfigPath(self):
        """
        Returns the main config path
        """
        return self.dir_root
           
    def setupTorrentList(self):
        torrentfilepath = os.path.join(self.getConfigPath(), "torrent.list")
        self.torrentconfig = ConfigReader(torrentfilepath, "list0")
               
    def postAppInit(self):
        """
        Called at app initialization
        Sets the icon and all the actions
        """
        # Set icon
        if wx.Platform == "__WXGTK__":
            img = wx.Image(os.path.join(self.getSharePath(), 'icon_bt.png'), wx.BITMAP_TYPE_PNG)
            self.icon = wx.IconFromBitmap(img.Scale(24, 24).ConvertToBitmap())
            self.smallIcon = wx.IconFromBitmap(img.Scale(20, 21).ConvertToBitmap())
        else:
            iconPath = os.path.join(self.getSharePath(), 'icon_bt.ico')
            self.icon = wx.Icon(iconPath, wx.BITMAP_TYPE_ICO)
            self.smallIcon = self.icon
            
##        iconPath = os.path.join(self.getSharePath(), 'icon_bt.ico')
##        self.icon = wx.Icon(iconPath, wx.BITMAP_TYPE_ICO)
##        if wx.Platform == "__WXGTK__":
##            icons = wx.IconBundle()
##            icons.AddIconFromFile(iconPath, wx.BITMAP_TYPE_ICO)
##            self.smallIcon = icons.GetIcon((16,16))
##        else:
##            self.smallIcon = self.icon
            
        # Load supported languages
        self.lang.loadLanguages()
        
        # Load Actions
        self.makeactionlist()

    def makeactionlist(self):
        """
        (Re)creates all actions
        """
        makeActionList()
            
    def getPath(self):
        """
        Returns the application path
        """
        return self.path.decode(sys.getfilesystemencoding())

    def getSharePath(self):
        path = os.path.join(sys.prefix, 'share', 'lh-abc')
        if not existsAndIsReadable(path):
            path = self.getPath()
        return path
	
    def makeBitmap(self, section, bitmap, trans_color = None):
        """
        Returns a new bitmap from the icons directory
        """
        if bitmap.endswith('.png'):
            bmpType = wx.BITMAP_TYPE_PNG
        else:
            bmpType = wx.BITMAP_TYPE_BMP
        button_bmp = wx.Bitmap(os.path.join(self.getSharePath(), "icons", section, bitmap), bmpType)
        if trans_color is not None:
            button_mask = wx.Mask(button_bmp, trans_color)
            button_bmp.SetMask(button_mask)
        return button_bmp

    def makeBitmapButton(self, parent, bitmap, tooltip, event, trans_color = wx.Colour(200, 200, 200),
                         btnstyle = None, ext = (10, 10), section = 'misc'):
        """
        Returns a bitmap button using an icon from the icons directory
        """
        if btnstyle is None:
            btnstyle = wx.BU_AUTODRAW
            
        if not isinstance(bitmap, wx.Bitmap):
            bitmap = self.makeBitmap(section, bitmap, trans_color)

        ID_BUTTON = wx.NewId()
        button_btn = wx.BitmapButton(parent, ID_BUTTON, bitmap, size=wx.Size(bitmap.GetWidth()+ext[0], bitmap.GetHeight()+ext[1]), style=btnstyle)  
        button_btn.SetToolTipString(tooltip)
        parent.Bind(wx.EVT_BUTTON, event, button_btn)
        return button_btn
    
    def makePopup(self, menu, event = None, label = "", extralabel = "", bindto = None, kind = wx.ITEM_NORMAL, ID = None):
        """
        Make an entry for a popup menu
        """
        text = ""
        if label != "":
            text = label
        text += extralabel

        if ID:
            newid = ID
        else:
            newid = wx.NewId()

        if event is not None:
            if bindto is None:
                bindto = menu
            bindto.Bind(wx.EVT_MENU, event, id = newid)
        menu.Append(newid, text, kind = kind)
        return newid
   
    def eta_value(self, n, truncate = 3):
        if n == -1:
            return '<unknown>'
        if not n:
            return ''
        n = int(n)
        week, r1 = divmod(n, 60 * 60 * 24 * 7)
        day, r2 = divmod(r1, 60 * 60 * 24)
        hour, r3 = divmod(r2, 60 * 60)
        minute, sec = divmod(r3, 60)
    
        if week > 1000:
            return '<unknown>'
    
        weekstr = '%d' % (week) + _('w')
        daystr = '%d' % (day) + _('d')
        hourstr = '%d' % (hour) + _('h')
        minutestr = '%02d' % (minute) + _('m')
        secstr = '%02d' % (sec) + _('s')
            
        if week > 0:
            text = weekstr
            if truncate > 1:
                text += ":" + daystr
            if truncate > 2:
                text += "-" + hourstr
        elif day > 0:
            text = daystr
            if truncate > 1:
                text += "-" + hourstr
            if truncate > 2:
                text += ":" + minutestr
        elif hour > 0:
            text = hourstr
            if truncate > 1:
                text += ":" + minutestr
            if truncate > 2:
                text += ":" + secstr   
        else:
            text = minutestr
            if truncate > 1:
                text += ":" + secstr

        return  text
                    
    def speed_format(self, s, truncate = 1, stopearly = None):
        return self.size_format(s, truncate, stopearly) + "/" + _('s')

    def size_format(self, s, truncate = None, stopearly = None, applylabel = True, rawsize = False, showbytes = False, labelonly = False, textonly = False):
        size = 0.0
        label = ""
        
        if truncate is None:
            truncate = 2
        
        if ((s < 1024) and showbytes and stopearly is None) or stopearly == "Byte":
            truncate = 0
            size = s
            text = _("Byte")
        elif ((s < 1048576) and stopearly is None) or stopearly == "KB":
            size = (s/1024.0)
            text = _("KB")
        elif ((s < 1073741824L) and stopearly is None) or stopearly == "MB":
            size = (s/1048576.0)
            text = _("MB")
        elif ((s < 1099511627776L) and stopearly is None) or stopearly == "GB":
            size = (s/1073741824.0)
            text = _("GB")
        else:
            size = (s/1099511627776.0)
            text = _("TB")

        if textonly:
            return text
        
        label = text
        if labelonly:
            return label
            
        if rawsize:
            return size
                        
        truncatestring = '%.' + str(truncate) + 'f'
        text = (truncatestring % size)
            
        if applylabel:
            text += ' ' + label
            
        return text
    
    def getBTParams(self, skipcheck = False):
        # Construct BT params
        ###########################
        btparams = []
        
        btparams.append("--display_interval")
        btparams.append(self.config.Read('display_interval'))


        # ipv6
        if sys.version_info >= (2,3) and socket.has_ipv6 and \
           self.config.Read('ipv6', "boolean"):
            btparams.append("--ipv6_enabled")
            btparams.append("1")
            btparams.append("--ipv6_binds_v4")
            btparams.append(self.config.Read('ipv6_binds_v4'))

        # See if we use a fixed port, or pick a random port from a range
        useportrange = self.config.Read('useportrange', 'boolean')
        minport = self.config.Read('minport', "int")
        maxport = self.config.Read('maxport', "int")
        useport = self.config.Read('useport', "int")
        
        # Pick a random port between minport and maxport
        if useportrange or useport < 0:
            useport = str(random.randint(minport, maxport))
        else:
            useport = str(useport)
        self.config.Write('useport', useport)
       
        # Use single port only
        btparams.append("--minport")
        btparams.append(useport)
        btparams.append("--maxport")
        btparams.append(useport)

        # Fast resume
        btparams.append("--selector_enabled")
        btparams.append(self.config.Read('fastresume'))
        
        btparams.append("--auto_kick")
        btparams.append(self.config.Read('kickban'))
        btparams.append("--security")
        btparams.append(self.config.Read('notsameip'))

        btparams.append("--max_upload_rate")
        btparams.append("0")

        # crypto_mode:
        #  @0 disabled
        #  @1 enabled
        #  @2 forced
        #  @3 stealth
        crypto_mode = self.config.Read('crypto_mode', "int")
        btparams.append("--crypto_stealth")
        btparams.append(str(int(crypto_mode==3)))
        btparams.append("--crypto_only")
        btparams.append(str(int(crypto_mode>=2)))
        btparams.append("--crypto_allowed")
        btparams.append(str(int(crypto_mode>=1)))
            
        paramlist = [ "ip", 
                      "bind", 
                      "alloc_rate", 
                      "alloc_type", 
                      "double_check", 
                      "triple_check", 
                      "lock_while_reading", 
                      "lock_files", 
                      "min_peers", 
                      "max_files_open", 
                      "max_connections",
                      "upnp_nat_access",
                      "natpmp",
                      "auto_flush",
                      "pex_allowed",
                      "expire_cache_data"]
        for param in paramlist:
            value = self.config.Read(param)
            if value != "":
                btparams.append("--" + param)
                btparams.append(value)

        config, args = parseargs(btparams, BTDefaults)
        
        config["dht"] = self.config.Read('dht', "boolean")
        config["tracker"] = self.config.Read('tracker', "boolean")
        
        return config

    def checkWinPath(self, parent, pathtocheck):
        if pathtocheck and pathtocheck[-1] == '\\' and pathtocheck != '\\\\':
            pathitems = pathtocheck[:-1].split('\\')
        else:
            pathitems = pathtocheck.split('\\')
        nexttotest = 1
        if isPathRelative(pathtocheck):
            # Relative path
            # Empty relative path is allowed
            if pathtocheck == '':
                return True
            fixedname = fixInvalidName(pathitems[0])
            if fixedname != pathitems[0]:
                dlg = wx.MessageDialog(parent, 
                                       pathitems[0] + '\n' + \
                                       _('This name cannot be used as a Windows file or folder name.') + '\n'+ \
                                       _('Suggested corrected name :') + '\n\n' + \
                                       fixedname, 
                                       _('Error'), wx.ICON_ERROR)
                dlg.ShowModal()
                dlg.Destroy()
                return False
        else:
            # Absolute path
            # An absolute path must have at least one '\'
            if not '\\' in pathtocheck:
                dlg = wx.MessageDialog(parent, pathitems[0] + '\n' + _('Invalid syntax in the path. Try adding a \\'), 
                                       _('Error'), wx.ICON_ERROR)
                dlg.ShowModal()
                dlg.Destroy()
                return False
            if pathtocheck[:2] != '\\\\':
                # Not a network path
                fixedname = fixWindowsName(pathitems[0], unit = True)
                if fixedname:
                    dlg = wx.MessageDialog(parent, 
                                           pathitems[0] + '\n' + \
                                           _('Invalid syntax in the path. Try adding a \\') + \
                                           fixedname, 
                                           _('Error'), wx.ICON_ERROR)
                    dlg.ShowModal()
                    dlg.Destroy()
                    return False
            else:
                # Network path
                nexttotest = 2

        for name in pathitems[nexttotest:]:
            fixedname = fixInvalidName(name)
            if fixedname != name:
                dlg = wx.MessageDialog(parent,
                                       name + '\n' + _('This name cannot be used as a Windows file or folder name.') + fixedname, 
                                       _('Error'), wx.ICON_ERROR)
                dlg.ShowModal()
                dlg.Destroy()
                return False

        return True
    
    def shutdownComputer(self):
        if (sys.platform == 'win32'):
            winver = sys.getwindowsversion()[3]
            if winver == VER_PLATFORM_WIN32_NT:
                shutdownthread = Thread(target = self.shutdown2k)
                shutdownthread.setDaemon(True)
                shutdownthread.start()
            elif winver == VER_PLATFORM_WIN32_WINDOWS:
                os.system('rundll32 shell32.dll,SHExitWindowsEx 9')
        else:
            func = utility.config.Read("shutdowncommand")
            os.execvp(func, [])
            
    def shutdown2k(self):
        AdjustTokenPrivileges(OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS), False,
                              [(LookupPrivilegeValue(None, SE_SHUTDOWN_NAME), SE_PRIVILEGE_ENABLED)])
        ExitWindowsEx(9)
        
    def setShutdownCommand(self, event = None):
        dialog = wx.TextEntryDialog(None, 
                                    _('Enter the shutdown command for your OS'), 
                                    _('Set Shutdown Command'), 
                                    utility.config.Read("shutdowncommand"))
        result = dialog.ShowModal()
        shutdowncommand = dialog.GetValue()
        dialog.Destroy()
        
        if result == wx.ID_OK:
            utility.config.Write("shutdowncommand", shutdowncommand)

    def install_open_new(self):
        browsers = ('xdg-open', 'gnome-open', 'nautilus', 'konqueror')
        userbrowser = self.config.Read('filemanager')
	
        # Detect Available Browsers
        for browser in browsers:
            if os.system("which " + browser + " >/dev/null 2>&1") == 0:
                self.browsers.append(browser)
        
        # Add Custom Browser
        if userbrowser:
            if userbrowser in self.browsers:
                self.browsers.remove(userbrowser)
                self.browsers.insert(0, userbrowser)
        
        # Set Browser To Use
        if self.browsers:
            self.browser = self.browsers[0]
        else:
            self.browser = ""

    def open_new(self, dest):
        # Fix Path
        if sys.platform == 'darwin':
            dest = 'file://%s' % dest
        elif sys.platform[:5] == 'linux' and not dest.startswith('/'):
            dest = self.path + '/' + dest

        # Known browser
        if self.browser:
            os.spawnlp(os.P_NOWAIT, self.browser, self.browser, dest)
        # Let python handle it
        else:
            open_new(dest)        
